use anyhow::Result;
use rbs::value;
use crate::models::state::CallRecord;
use crate::models::call::DbCallRecord;

/// 通话记录数据访问层
pub struct CallRepository;

impl CallRepository {
    pub async fn list() -> Result<Vec<CallRecord>> {
        let list: Vec<DbCallRecord> = crate::infra::database::rb()
            .query_decode(
                r#"
                SELECT id, target, target_display, call_type, status, timestamp, duration
                FROM call_records
                ORDER BY timestamp DESC
                "#,
                vec![],
            )
            .await?;
        Ok(list.into_iter().map(CallRecord::from).collect())
    }

    pub async fn search(query: &str) -> Result<Vec<CallRecord>> {
        let pattern = format!("%{}%", query);
        let list: Vec<DbCallRecord> = crate::infra::database::rb()
            .query_decode(
                r#"
                SELECT id, target, target_display, call_type, status, timestamp, duration
                FROM call_records
                WHERE target LIKE ? OR target_display LIKE ?
                ORDER BY timestamp DESC
                "#,
                vec![value!(pattern.clone()), value!(pattern)],
            )
            .await?;
        Ok(list.into_iter().map(CallRecord::from).collect())
    }

    pub async fn add(record: CallRecord) -> Result<()> {
        let db_record = DbCallRecord::from(record);
        crate::infra::database::rb()
            .exec(
                r#"
                INSERT OR REPLACE INTO call_records
                (id, target, target_display, call_type, status, timestamp, duration)
                VALUES(?,?,?,?,?,?,?)
                "#,
                vec![
                    value!(db_record.id),
                    value!(db_record.target),
                    value!(db_record.target_display),
                    value!(db_record.call_type),
                    value!(db_record.status),
                    value!(db_record.timestamp),
                    value!(db_record.duration),
                ],
            )
            .await?;
        Ok(())
    }

    pub async fn update_status(call_id: &str, status: crate::models::state::CallStatus, duration: Option<u32>) -> Result<()> {
        let status_str = match status {
            crate::models::state::CallStatus::Connected => "Connected",
            crate::models::state::CallStatus::Failed => "Failed",
            crate::models::state::CallStatus::Cancelled => "Cancelled",
            crate::models::state::CallStatus::NoAnswer => "NoAnswer",
        };
        crate::infra::database::rb()
            .exec(
                "UPDATE call_records SET status = ?, duration = ? WHERE id = ?",
                vec![
                    value!(status_str),
                    value!(duration.map(|d| d as i64)),
                    value!(call_id),
                ],
            )
            .await?;
        Ok(())
    }
}

